home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
pascal
/
crti.zip
/
CRTI.PAS
Wrap
Pascal/Delphi Source File
|
1988-03-03
|
18KB
|
350 lines
UNIT CRTi; {version 1.00 of 03/03/88}
{Copyright (c) 1988 by Carley Phillips. Placed in the PUBLIC DOMAIN.}
{
Many of the message threads on Compuserve's BPROGA DL 2 involve the use (and
mis-use) of the CRT unit provided with Turbo 4. These routines were written
to take some of the mystery out of what CRT routines do and do not do.
This unit is an input-only replacement for Borland's CRT. This means that:
1. only the input and the misc functions (e.g. Sound) are implemented;
2. the parts which have to do with screen output are omitted; and
3. you have access to the source so you can change what you don't like.
This allows your programs to avoid USEing CRT at all if your video output
is done with Qwik40, FastWrite, or other packages. If you use CRTi anywhere,
then make sure none of your units use CRT because the conflicts which may
result may be very difficult to debug.
Note that the equivalent of a Turbo variable (which they should have made
public) is contained in HadControlBreak. This is the variable set by the
control-break handler if CheckBreak is true. Normally Turbo tests this
during ReadKey and during screen output. Your program can test this at
any time, however, such as in your replacement screen routines or during
a long mathematical calculation.
There are two new public routines here:
1. a keyboard flushing routine; and
2. an abort routine you can call if your program finds HadControlBreak true.
I will update these routines if anyone notifies me of bugs or of any way in
which these routines do not provide satisfactory duplicates of Borland
functionality.
Comments, suggestions, bug reports, etc. should be sent on Compuserve (via
EasyPlex since I'm not necessarily on every few days) to
Carley Phillips, 76630,3312.
}
{*****************************************************************************}
INTERFACE
var
CheckBreak : boolean; {false means ignore ^Break}
SaveInt1B : pointer; {where old interrupt 1B address is saved}
HadControlBreak : boolean; {set by ^Break handler if CheckBreak true}
procedure Delay (mSec : word);
{
Direct replacement for CRT.Delay. Delays mSec number of milliseconds.
Note that, like Borland's CRT unit, a delay count is determined during
initialization. This means that if you change your machine speed after
starting a program, the delay values will no longer be what you intended them
to be.
}
procedure Sound (Hz : word);
{
Direct replacement for CRT.Sound. Starts a Hz frequency tone until it is
turned off by NoSound.
}
procedure NoSound;
{
Direct replacement for CRT.NoSound. Stops a tone started with Sound.
}
function Keypressed : boolean;
{
Direct replacement for CRT.Keypressed. If you like, you can also check for
a control break here by un-commenting the indicated lines.
}
function ReadKey : char;
{
Direct replacement for CRT.ReadKey.
}
procedure FlushKeyboard;
{
NEW public routine to flush the BIOS keyboard buffer. That is, unless the
user is extraordinarily lucky with his timing of new input, Keypressed will
be false immediatedly following FlushKeyboard. Normally one flushes the
keyboard buffer in situations such as displaying an error message and then
waiting on the user to press a key. If the buffer is not flushed, then the
user may have typed ahead enough that the error message will be on the screen
for too short a time to be read.
}
procedure ControlBreakAbort;
{
NEW public abort routine called when ReadKey detects that an allowed ^Break has
been entered. Borland does something similar, but you are free to replace this
with other code or even an external routine. Alternatively, you can use this
routine from your code if you find that HadControlBreak has become true.
}
{*****************************************************************************}
IMPLEMENTATION
var
Cpm : word; {counts per msec; initialized by InitDelay; used by Delay}
Scan: byte; {saves scan code for Keypressed and ReadKey}
ExitSave : pointer; {place to save old ExitProc}
{*****************************************************************************}
procedure Delay (mSec : word);
begin
Inline( {Assembly by Inline 03/03/88 22:28}
$8B/$56/<MSEC/ { mov DX,[BP+<mSec];get number of msec}
$09/$D2/ { or DX,DX ;check it}
$74/$17/ { jz quit ;quit if 0 delay}
$BF/>CPM/ { mov DI,>Cpm ;setup addr for subr}
$8B/$05/ { mov AX,[DI] ;delay count for 1msec}
$89/$C1/ {onemsec: mov CX,AX ;init delay subr counter}
$E8/$06/$00/ { call subr ;call delay subr}
$4A/ { dec DX ;count that we've done 1}
$75/$F8/ { jnz onemsec ;loop for each msec}
$E9/$07/$00/ { jmp quit ;skip over subroutine}
$3A/$05/ {subr: cmp AL,[DI] ;check if constant chngd}
$75/$02/ { jnz out ;it never will change}
$E2/$FA/ { loop subr ;count and loop for msec}
$C3 {out: ret ;return from local subr}
); {quit: ;label for end of inline}
end;
{*****************************************************************************}
procedure Sound (Hz : word);
begin
Inline( {Assembly by Inline 03/03/88 22:28}
$8B/$4E/<HZ/ { mov CX,[BP+<Hz] ;get frequency}
$B8/$DD/$34/ { mov AX,$34DD ;load lsh of 1,193,181}
$BA/$12/$00/ { mov DX,$0012 ;load msh of 1,193,181}
$39/$CA/ { cmp DX,CX ;check frequency}
$73/$1A/ { jnb quit ;quit if too small}
$F7/$F1/ { div CX ;calculate timer divider}
$89/$C1/ { mov CX,AX ;save quotient}
$E4/$61/ { in AL,$61 ;get sense data}
$A8/$03/ { test AL,$03 ;check for two lsb}
$75/$08/ { jnz set ;skip if on}
$0C/$03/ { or AL,$03 ;turn on two lsb}
$E6/$61/ { out $61,AL ;turn them on}
$B0/$B6/ { mov AL,$B6 ;load control value}
$E6/$43/ { out $43,AL ;output to timer control}
$88/$C8/ {set: mov AL,CL ;get lsh of quotient}
$E6/$42/ { out $42,AL ;output to timer2}
$88/$E8/ { mov AL,CH ;get msh of quotient}
$E6/$42 { out $42,AL ;output to timer2}
); {quit: ;label for end of inline}
end;
{*****************************************************************************}
procedure NoSound;
begin
Inline( {Assembly by Inline 03/03/88 22:28}
$E4/$61/ { in AL,$61 ;get sense data}
$24/$FC/ { and AL,$FC ;turn off two lsb}
$E6/$61 { out $61,AL ;put it back}
); {quit: ;label for end of inline}
end;
{*****************************************************************************}
function KeyPressed : boolean;
begin
(*
if HadControlBreak then {un-comment this if you want to check ^Break here}
ControlBreakAbort;
*)
Inline( {Assembly by Inline 03/03/88 22:28}
$80/$3E/>SCAN/$00/ { cmp Byte Ptr[>Scan],$00;check scan code}
$75/$08/ { jnz yes ;not 0 = we saved one}
$B4/$01/ { mov AH,$01 ;check for char}
$CD/$16/ { int $16 ;using BIOS}
$B0/$00/ {